/**
 * 弹幕特殊符号处理工具
 * 用于解决特殊符号在弹幕中显示异常的问题
 */
class DanmakuFilter {
    constructor(options = {}) {
        // 默认配置
        this.config = {
            // 允许的HTML标签白名单
            allowedTags: ['b', 'i', 'u', 's', 'em', 'strong', 'span', 'a'],
            // 允许的HTML属性白名单
            allowedAttributes: {
                'a': ['href', 'target'],
                'span': ['style']
            },
            // 允许的CSS属性白名单
            allowedStyles: ['color', 'font-size', 'font-weight', 'font-style', 'text-decoration'],
            // 特殊符号替换映射
            specialCharMap: {
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '"': '&quot;',
                "'": '&#39;'
            },
            // 表情符号映射
            emojiMap: {
                ':smile:': '😊',
                ':laugh:': '😂',
                ':heart:': '❤️',
                ':star:': '⭐',
                ':thumbup:': '👍',
                ':thumbdown:': '👎',
                ':clap:': '👏',
                ':cry:': '😭',
                ':angry:': '😠',
                ':shy:': '😊'
            }
        };
        
        // 合并用户配置
        Object.assign(this.config, options);
        
        // 构建表情符号正则表达式
        this.emojiRegex = new RegExp(`(${Object.keys(this.config.emojiMap).join('|')})`, 'g');
    }
    
    /**
     * 过滤和处理弹幕文本
     * @param {string} text 原始弹幕文本
     * @returns {string} 处理后的弹幕文本
     */
    process(text) {
        if (!text || typeof text !== 'string') {
            return '';
        }
        
        // 1. 基础HTML实体转义
        text = this.escapeBasicHtmlEntities(text);
        
        // 2. 安全地处理HTML标签
        text = this.sanitizeHtml(text);
        
        // 3. 替换表情符号
        text = this.replaceEmojis(text);
        
        // 4. 自定义特殊符号处理（可根据需求扩展）
        text = this.processCustomSpecialChars(text);
        
        return text;
    }
    
    /**
     * 转义基础HTML实体
     * @param {string} text 原始文本
     * @returns {string} 转义后的文本
     */
    escapeBasicHtmlEntities(text) {
        return text.replace(/[&<>"']/g, char => this.config.specialCharMap[char] || char);
    }
    
    /**
     * 安全地处理HTML标签，防止XSS攻击
     * @param {string} html 原始HTML文本
     * @returns {string} 安全的HTML文本
     */
    sanitizeHtml(html) {
        // 简单实现：使用正则表达式移除不在白名单中的标签和属性
        // 注意：这不是一个完整的XSS防护方案，实际生产环境中建议使用专门的库如DOMPurify
        
        // 移除不在白名单中的标签
        html = html.replace(/<(\/?)([^>\s]+)([^>]*)>/g, (match, slash, tagName, attrs) => {
            if (this.config.allowedTags.includes(tagName.toLowerCase())) {
                // 处理允许的标签，过滤不安全的属性
                const safeAttrs = this.filterAttributes(tagName, attrs);
                return `<${slash}${tagName}${safeAttrs}>`;
            }
            // 不允许的标签，替换为文本
            return `&lt;${slash}${tagName}${attrs}&gt;`;
        });
        
        return html;
    }
    
    /**
     * 过滤标签属性，只保留允许的属性
     * @param {string} tagName 标签名
     * @param {string} attrs 属性字符串
     * @returns {string} 过滤后的属性字符串
     */
    filterAttributes(tagName, attrs) {
        tagName = tagName.toLowerCase();
        const allowedAttrs = this.config.allowedAttributes[tagName] || [];
        
        // 提取属性名和值
        const attrRegex = /([^\s=]+)(\s*=\s*("[^"]*"|'[^']*'|[^>\s]*))?/g;
        let result = '';
        
        let match;
        while ((match = attrRegex.exec(attrs)) !== null) {
            const attrName = match[1].toLowerCase();
            
            if (allowedAttrs.includes(attrName)) {
                // 处理style属性
                if (attrName === 'style') {
                    const styleValue = match[3] || '';
                    const safeStyle = this.filterStyles(styleValue);
                    if (safeStyle) {
                        result += ` style="${safeStyle}"`;
                    }
                } else {
                    // 其他允许的属性
                    result += ` ${attrName}="${match[3] || ''}"`;
                }
            }
        }
        
        return result;
    }
    
    /**
     * 过滤CSS样式，只保留允许的样式属性
     * @param {string} style 样式字符串
     * @returns {string} 过滤后的样式字符串
     */
    filterStyles(style) {
        const allowedStyles = this.config.allowedStyles;
        const styleRegex = /([^:\s]+)\s*:\s*([^;]+);?/g;
        let result = '';
        
        let match;
        while ((match = styleRegex.exec(style)) !== null) {
            const property = match[1].trim().toLowerCase();
            const value = match[2].trim();
            
            if (allowedStyles.includes(property)) {
                // 检查颜色值是否合法
                if (property === 'color' && !this.isValidColor(value)) {
                    continue;
                }
                
                // 检查字体大小是否合法
                if (property === 'font-size' && !this.isValidSize(value)) {
                    continue;
                }
                
                result += `${property}:${value};`;
            }
        }
        
        return result;
    }
    
    /**
     * 验证颜色值是否合法
     * @param {string} color 颜色值
     * @returns {boolean} 是否合法
     */
    isValidColor(color) {
        // 简单验证：检查是否是合法的颜色格式
        return /^(#([0-9A-Fa-f]{3}){1,2}|rgb\(\d{1,3},\s*\d{1,3},\s*\d{1,3}\)|rgba\(\d{1,3},\s*\d{1,3},\s*\d{1,3},\s*[\d.]+\)|hsl\(\d{1,3},\s*[\d.]+%,\s*[\d.]+%\)|hsla\(\d{1,3},\s*[\d.]+%,\s*[\d.]+%,\s*[\d.]+\)|[a-z]+)$/.test(color);
    }
    
    /**
     * 验证大小值是否合法
     * @param {string} size 大小值
     * @returns {boolean} 是否合法
     */
    isValidSize(size) {
        // 简单验证：检查是否是合法的尺寸格式
        return /^\d+(\.\d+)?(px|em|rem|%)$/.test(size);
    }
    
    /**
     * 替换表情符号
     * @param {string} text 原始文本
     * @returns {string} 替换后的文本
     */
    replaceEmojis(text) {
        return text.replace(this.emojiRegex, match => this.config.emojiMap[match] || match);
    }
    
    /**
     * 处理自定义特殊符号（可根据需求扩展）
     * @param {string} text 原始文本
     * @returns {string} 处理后的文本
     */
    processCustomSpecialChars(text) {
        // 示例：处理某些特殊的数学符号或其他自定义符号
        return text
            .replace(/×/g, '×')  // 保留正确的乘号
            .replace(/÷/g, '÷')  // 保留正确的除号
            .replace(/【/g, '【')  // 保留中文括号
            .replace(/】/g, '】');
    }
    
    /**
     * 设置自定义配置
     * @param {object} options 配置选项
     */
    setConfig(options) {
        Object.assign(this.config, options);
        
        // 重新构建表情符号正则表达式
        this.emojiRegex = new RegExp(`(${Object.keys(this.config.emojiMap).join('|')})`, 'g');
    }
}

// 示例使用
const danmakuFilter = new DanmakuFilter();

// 处理弹幕文本
function processDanmakuText(text) {
    return danmakuFilter.process(text);
}    